package com.isyscore.os.metadata.kettle.vis;

import cn.hutool.core.text.StrPool;
import com.isyscore.os.core.util.ApplicationUtils;
import com.isyscore.os.metadata.enums.KettleDataFlowNodeGroupType;
import com.isyscore.os.metadata.enums.KettleDataFlowNodeType;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.validation.SmartValidator;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Data
@Slf4j
public abstract class VisNode {

    @ApiModelProperty("节点的唯一标识")
    private String id;

    @ApiModelProperty("节点名称")
    private String nodeName;


    @ApiModelProperty(hidden = true)
    private List<VisNode> incomings;

    @ApiModelProperty(hidden = true)
    private List<VisNode> outgoings;


    public void addIncomingNode(VisNode incomingNode) {
        if (incomings == null) {
            incomings = Lists.newArrayList();
        }
        incomings.add(incomingNode);
    }

    public void addOutgoingNode(VisNode outgoingNode) {
        if (outgoings == null) {
            outgoings = Lists.newArrayList();
        }
        outgoings.add(outgoingNode);
    }

    /**
     * 结合节点的incomings和outgoings的属性对节点进行校验，避免节点在dataflow中的位置
     * 不符合规范
     *
     * @return 验证错误信息
     */
     public String validate(){
         SmartValidator validator = ApplicationUtils.getBean(SmartValidator.class);
         BeanPropertyBindingResult result = new BeanPropertyBindingResult(this, this.getClass().getName());
         validator.validate(this, result);
         if (result.hasErrors()) {
             return result.getAllErrors().stream().map(ObjectError::getDefaultMessage).collect(Collectors.joining(StrPool.COMMA));
         }
         return null;
     };

    /**
     * 将前端传入的节点配置值转换为实际的节点属性，每个不同的节点类型应该根据自身的
     * 属性情况覆盖该方法
     *
     * @param params 前端传入的某个节点的配置值
     */
    abstract public void valueOf(Map<String, Object> params);

    @ApiModelProperty(hidden = true)
    public Long getDbSourceId() {
        return null;
    }

    @ApiModelProperty(hidden = true)
    public String getDatabaseName() {
        return null;
    }

    /**
     * 获得节点分组类型
     * @return
     */
    abstract public KettleDataFlowNodeGroupType getGroupType();
    /**
     * 获得节点类型
     * @return
     */
    abstract public KettleDataFlowNodeType getNodeType();

    /**
     * 是否是多路输出的
     * @return
     */
    public boolean isMultiOut(){
        return  false;
    }
}
